package io.gitee.thghh.generate.core.datatype;


import com.github.drinkjava2.jdialects.Type;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 类型映射util
 *
 * @author pengzhikang
 * @date 2025/03/30
 * @since 1.0.0
 */
public class TypeMapUtil {

    private static final Map<Type, Class<?>> TYPE_TO_JAVA_MAP = new HashMap<>();

    static {
        TYPE_TO_JAVA_MAP.put(Type.NUMERIC, BigDecimal.class);
        TYPE_TO_JAVA_MAP.put(Type.BIGINT, Long.class);
        TYPE_TO_JAVA_MAP.put(Type.BOOLEAN, Boolean.class);
        TYPE_TO_JAVA_MAP.put(Type.TINYINT, Byte.class);
        TYPE_TO_JAVA_MAP.put(Type.SMALLINT, Short.class);
        TYPE_TO_JAVA_MAP.put(Type.VARCHAR, String.class);
        TYPE_TO_JAVA_MAP.put(Type.BINARY, byte[].class);
        TYPE_TO_JAVA_MAP.put(Type.BIT, Boolean.class);
        TYPE_TO_JAVA_MAP.put(Type.BLOB, String.class);
        //JDBC的CHAR类型可能是有长度的，还是映射成 实体的String类型比较安全
        TYPE_TO_JAVA_MAP.put(Type.CHAR, String.class);
        TYPE_TO_JAVA_MAP.put(Type.CLOB, String.class);
        TYPE_TO_JAVA_MAP.put(Type.DECIMAL, BigDecimal.class);
        TYPE_TO_JAVA_MAP.put(Type.DOUBLE, Double.class);
        TYPE_TO_JAVA_MAP.put(Type.FLOAT, Float.class);
        TYPE_TO_JAVA_MAP.put(Type.INTEGER, Integer.class);
        TYPE_TO_JAVA_MAP.put(Type.JAVA_OBJECT, Object.class);
        TYPE_TO_JAVA_MAP.put(Type.LONGNVARCHAR, String.class);
        TYPE_TO_JAVA_MAP.put(Type.LONGVARBINARY, String.class);
        TYPE_TO_JAVA_MAP.put(Type.LONGVARCHAR, String.class);
        TYPE_TO_JAVA_MAP.put(Type.NCHAR, String.class);
        TYPE_TO_JAVA_MAP.put(Type.NCLOB, String.class);
        TYPE_TO_JAVA_MAP.put(Type.NVARCHAR, String.class);
        TYPE_TO_JAVA_MAP.put(Type.UNKNOW, Object.class);
        TYPE_TO_JAVA_MAP.put(Type.REAL, Float.class);
        TYPE_TO_JAVA_MAP.put(Type.VARBINARY, String.class);
        TYPE_TO_JAVA_MAP.put(Type.DATE, java.util.Date.class);
        TYPE_TO_JAVA_MAP.put(Type.TIME, java.sql.Time.class);
        TYPE_TO_JAVA_MAP.put(Type.TIMESTAMP, java.sql.Timestamp.class);

        TYPE_TO_JAVA_MAP.put(Type.DATETIME, java.sql.Timestamp.class);
        TYPE_TO_JAVA_MAP.put(Type.MEDIUMINT, java.lang.Integer.class);
        TYPE_TO_JAVA_MAP.put(Type.INT, java.lang.Integer.class);

        // mysql
        TYPE_TO_JAVA_MAP.put(Type.TINYBLOB, byte[].class);
        TYPE_TO_JAVA_MAP.put(Type.TINYTEXT, String.class);
        TYPE_TO_JAVA_MAP.put(Type.TEXT, String.class);
        TYPE_TO_JAVA_MAP.put(Type.MEDIUMTEXT, byte[].class);
        TYPE_TO_JAVA_MAP.put(Type.LONGBLOB, byte[].class);
        TYPE_TO_JAVA_MAP.put(Type.MEDIUMBLOB, byte[].class);
        TYPE_TO_JAVA_MAP.put(Type.LONGTEXT, String.class);
        TYPE_TO_JAVA_MAP.put(Type.YEAR, Integer.class);
        TYPE_TO_JAVA_MAP.put(Type.JSON, String.class);

        // oracle
        TYPE_TO_JAVA_MAP.put(Type.VARCHAR2, String.class);
        TYPE_TO_JAVA_MAP.put(Type.BINARY_FLOAT, Float.class);
        TYPE_TO_JAVA_MAP.put(Type.DOUBLE_PRECISION, Double.class);
        TYPE_TO_JAVA_MAP.put(Type.BINARY_DOUBLE, Double.class);
        TYPE_TO_JAVA_MAP.put(Type.TIMESTAMP_WITH_TIME_ZONE, java.sql.Timestamp.class);
        TYPE_TO_JAVA_MAP.put(Type.TIMESTAMP_WITH_LOCAL_TIME_ZONE, java.sql.Timestamp.class);
        TYPE_TO_JAVA_MAP.put(Type.INTERVAL_YEAR_TO_MONTH, java.time.Period.class);
        TYPE_TO_JAVA_MAP.put(Type.INTERVAL_DAY_TO_SECOND, java.time.Duration.class);
    }

    /**
     * 方言类型到java类型
     *
     * @param type 类型
     * @return {@link Class }<{@link ? }>
     * @author pengzhikang
     * @date 2025/03/30
     */
    public static Class<?> dialectTypeToJavaType(Type type) {// NOSONAR
        return TYPE_TO_JAVA_MAP.get(type);
    }

    /**
     * 方言类型到类名
     *
     * @param type 类型
     * @return {@link String }
     * @author pengzhikang
     * @date 2025/03/30
     */
    public static String dialectTypeToClassName(Type type) {// NOSONAR
        Class<?> clazz = TYPE_TO_JAVA_MAP.get(type);
        if (clazz == null) {
            return null;
        }
        String name = clazz.getName();
        if ("[B".equals(name)) {
            return "byte[]";
        }
        return name;
    }
}
